package main

import (
	"bytes"
	"github.com/gorilla/websocket"
	"sync"
	"time"
)

var logger = NewLogger("core", false)
var roomManager = HouseManager

type Client struct {
	Socket *websocket.Conn
	Send   chan []byte

	UserId    string
	PlayerNo  uint8 // 玩家在房间内的座位号下标索引, 由客户端加入房间请求里传入
	RoomNo    string
	Room      *Room
	MaxNumber uint8

	LastAction []byte
	Actions    chan []byte
}

// 客户端进入房间, flag 进入成功或失败
func (c *Client) EnterRoom() (flag bool, room *Room) {

	flag = true

	roomManager.mutex.Lock()

	room = roomManager.roomMap[c.RoomNo]
	if room == nil {
		room = &Room{
			roomNo:      c.RoomNo,
			max:         c.MaxNumber,
			players:     make([]*Client, c.MaxNumber),
			playerCount: 0,
			frameNum:    0,
			mutex:       new(sync.Mutex),
		}
		roomManager.roomMap[c.RoomNo] = room
	}

	if room.started || room.isFull() {
		return false, room
	}

	// 客户端关联一个房间
	c.Room = room
	// 客户端初始动作指令channel
	c.Actions = make(chan []byte, 10)

	roomManager.mutex.Unlock()

	// 按客户端坐落到的房间对应下标位置
	room.AddPlayer(c)

	return flag, room
}

func (c *Client) LeaveRoom() {
	if c.Room != nil {
		// 将玩家从房间内移除
		c.Room.RemovePlayer(c)

		if c.Room.TryEndGame() {
			roomManager.RemoveRoom(c.Room)
		}
	}
}

func (c *Client) Read() {
	defer func() {
		//CManager.delClient(c)
		CManager.Unregister <- c
	}()
	defer func() {
		if err := recover(); err != nil {
			logger.Printf("[ERR] Read: %s", err)
		}
	}()

	for {
		c.Socket.SetReadDeadline(time.Now().Add(time.Second * 15))
		messageType, data, err := c.Socket.ReadMessage()
		if err != nil {
			logger.Println(err, " - 读取数据错误")
			break
		}

		if messageType != websocket.BinaryMessage {
			logger.Println("错误的消息类型", messageType)
			break
		}

		//logger.Printf("读取到客户端数据长度: %d", len(data))

		dataBuffer := bytes.NewBuffer(data)
		messageModel := &MessageModel{}
		messageModel.read(dataBuffer)

		Handlers.Handle(c, messageModel)
	}
}

func (c *Client) Write() {
	defer func() {
		c.Socket.Close()
	}()
	defer func() {
		if err := recover(); err != nil {
			logger.Printf("[ERR] Write: %s", err)
		}
	}()

	for {
		select {
		case message, ok := <-c.Send:
			if !ok {
				c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}
			c.Socket.SetWriteDeadline(time.Now().Add(time.Second * 15))
			err := c.Socket.WriteMessage(websocket.BinaryMessage, message)
			if err != nil {
				logger.Println("[ERR] WriteMessage: ", err)
			}
		}
	}
}
